﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace LitFramework
{
    /// <summary>
    /// 单例管理类
    /// </summary>
    public class SingletonManager : MonoBehaviour
    {
        private static SingletonManager _instance;
        public static SingletonManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    GameObject go = new GameObject("SingletonManager");
                    _instance = go.AddComponent<SingletonManager>();
                    _instance.singletons = new List<ISingleton>();
                    _instance.singletonUpdates = new List<ISingletonUpdate>();
                    DontDestroyOnLoad(go);
                }
                return _instance;
            }
        }

        /// <summary>
        /// 持有实例引用
        /// </summary>
        private List<ISingleton> singletons;
        private List<ISingletonUpdate> singletonUpdates;
        /// <summary>
        /// 重排序脏标记
        /// </summary>
        private bool isDirty;

        /// <summary>
        /// 添加单例
        /// </summary>
        /// <param name="singleton"></param>
        public void CreateSingleton<T>() where T : Singleton<T>, ISingleton, new()
        {
            for (int i = 0; i < singletons.Count; i++)
            {
                if (singletons[i].GetType() == typeof(T))
                {
                    Debug.LogError($"[SingletonManager] 单例类{typeof(T)}已存在");
                    return;
                }
            }
            var singleton = new T();
            singleton.OnInit();
            singletons.Add(singleton);
            if(singleton is ISingletonUpdate update)
            {
                singletonUpdates.Add(update);
            }
            isDirty = true;
        }

        /// <summary>
        /// 移除单例
        /// </summary>
        /// <param name="singleton"></param>
        public void DestroySingleton<T>() where T : Singleton<T>, ISingleton, new()
        {
            if (singletons == null || singletons.Count == 0) return;
            for (int i = 0; i < singletons.Count; i++)
            {
                if (singletons[i].GetType() == typeof(T))
                {
                    MethodInfo methodInfo = typeof(T).GetMethod("Destroy", BindingFlags.NonPublic | BindingFlags.Instance);
                    methodInfo.Invoke(singletons[i], null);
                    singletons.RemoveAt(i);
                    break;
                }
            }
            isDirty = true;
        }

        private void Update()
        {
            if (singletonUpdates == null) return;
            if (singletonUpdates.Count <= 0) return;

            if (isDirty)
            {
                singletonUpdates = singletonUpdates.OrderBy(s => s.Order).ToList();
            }
            for (int i = 0; i < singletonUpdates.Count; i++)
            {
                singletonUpdates[i].OnUpdate();
            }
        }

        private void OnDestroy()
        {
            if (singletons != null
                && singletons.Count > 0)
            {
                for (int i = 0; i < singletons.Count; i++)
                {
                    var type = singletons[i].GetType();
                    MethodInfo methodInfo = type.GetMethod("Destroy", BindingFlags.NonPublic | BindingFlags.Instance);
                    methodInfo.Invoke(singletons[i], null);
                }
                singletons.Clear();
            }
            _instance = null;
        }
    }
}